#include "GY_Object.h"

#include <QRandomGenerator>
#include <QTime>
#include <QUuid>
#include <QDebug>
#include "GY_GraphicsReflection.h"

GY_Object::GY_Object(const QString &guid, QObject *parent)
    :QObject(parent)
{
    m_Guid = guid;
//    setObjName(QString("gItemName_%1")
//               .arg(QUuid::createUuid().toString().remove("{").remove("-").remove("}")));
//    setObjName(guid);
//    connect(this,&GY_Object::updatePropertyEvent,[=](const GY_Object* pObject,const QString &propertyName,
//            const QVariant &propertyValue,const PropertyType& type) {
//        qDebug()<<pObject<<propertyName<<propertyValue<<type;
//    });
}

void GY_Object::setCenterPointF(const QPointF &pointF)
{
    centerPointF = pointF;
    //标记数据，key=2表示中心点位置
    setUserData(GY_ENUM::CenterPointF,QVariant::fromValue(pointF));
}

QPointF GY_Object::getCenterPointF()
{
    return centerPointF;
}

void GY_Object::setEditPointF(QMap<QVariant, QPointF> &map)
{
    editPointFMap = map;
    setUserData(GY_ENUM::EditPointF,QVariant::fromValue(map));
}

void GY_Object::setEditPointF(const QVariant &key, const QPointF &p)
{
    editPointFMap.insert(key,p);
    setUserData(GY_ENUM::EditPointF,QVariant::fromValue(editPointFMap));
}

void GY_Object::deleeteEditPointF(const QVariant &key)
{
    editPointFMap.remove(key);
    //标记数据，key=1表示编辑点位置
    setUserData(GY_ENUM::EditPointF,QVariant::fromValue(editPointFMap));
}

bool GY_Object::updateObjectName(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QString>())
        return false;
    m_PropertyInfoMap[name].propertyValue = value;
    return true;
}

QMap<QString, GY_PropertyInfo> GY_Object::getInheritAttributes(const QString &name, GY_Object *obj)
{
    if(((GY_Object*)(obj->parent())) == nullptr || !(((GY_Object*)(obj->parent()))->getPropertyMap().contains(name))) {
        return obj->getPropertyMap();
    }
    if(obj->getPropertyMap()[name].propertyValue.toBool() == false) {
        return obj->getPropertyMap();
    }else {
        return getInheritAttributes(name, (GY_Object*)(obj->parent()));
    }
}

void GY_Object::setpItem(QGraphicsItem *pItem)
{
    m_pItem = pItem;
}

void GY_Object::originalVersion(GY_Object **obj)
{
    GY_Object* tmp = this->copyItem();
    *obj = tmp;
}

QMap<QVariant, QPointF> GY_Object::getEditPointF()
{
    return editPointFMap;
}

GY_Object::~GY_Object()
{
}

void GY_Object::setConnect()
{
    QMap<QString,GY_PropertyInfo>::Iterator iter = m_PropertyInfoMap.begin();
    while (iter != m_PropertyInfoMap.end()) {
        iter.value().setConnect();
        ++iter;
    }
}

QString GY_Object::getObjName() const
{
//    return m_pItem->data(GY_ENUM::ObjectName).toString();
    if(m_PropertyInfoMap.contains("ObjectName")) {
        return m_PropertyInfoMap["ObjectName"].propertyValue.toString();
    }
    return QString();
}

void GY_Object::setObjName(const QString &value)
{
    if(!m_PropertyInfoMap.contains("ObjectName")) {
        GY_PropertyInfo ObjectName(this);
        ObjectName.propertyName = "ObjectName";
        ObjectName.propertyValue = value;
        ObjectName.updateType = Update|OrdinaryAttributes;
        ObjectName.propertyType = QStringPropertyType;
        ObjectName.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_Object::updateObjectName;
        m_PropertyInfoMap.insert(ObjectName.propertyName,ObjectName);
        m_PropertyInfoMap[ObjectName.propertyName].setConnect();
    }else {
        updateObjectName("ObjectName",value);
    }
//    objName = value;
    //    m_pItem->setData(GY_ENUM::ObjectName,objName);
}

QString GY_Object::getGuid() const
{
    return m_Guid;
}

void GY_Object::setGuid(const QString &guid)
{
    m_Guid = guid;
}

void GY_Object::setUserData(const int &id, const QVariant &val)
{
    m_pItem->setData(id,val);
}

QGraphicsItem *GY_Object::getGraphicsItem()
{
    return  m_pItem;
}

QVariant GY_Object::getUserData(const int &id)
{
    return m_pItem->data(id);
}

bool GY_Object::updateProperty(const QString &name, const QVariant &value, const DataType &type)
{
//    qDebug() << "_________" << this->getObjName() << name << value << "-------------";
    //分隔 "."
    QStringList nameList = name.split(".");
    QVariant tmpValue = value;
    QString tmpName = name;

    if(nameList.size()==1)
    {
        //map中没有name退出
        if(!m_PropertyInfoMap.contains(tmpName))
        {
            return false;
        }
        //传入坐标不是scene则转换为scene
        if(type == PointDefaultType) {
            if(m_pItem->parentItem() && ((m_PropertyInfoMap.value(name).updateType&PointOfRelative)==PointOfRelative)) {
                tmpValue = m_pItem->mapToScene(m_pItem->mapFromParent(value.toPointF()));
            }
        }else if((type == PointParentType) && ((m_PropertyInfoMap.value(name).updateType&PointOfRelative)==PointOfRelative)) {
            tmpValue = m_pItem->mapToScene(m_pItem->mapFromParent(value.toPointF()));
        }
    }else {
        //map中既没有name也没有name.后缀退出
        if(!m_PropertyInfoMap.contains(nameList.at(0)) && !m_PropertyInfoMap.contains(tmpName))
        {
            return false;
        }
        if(m_PropertyInfoMap.value(nameList.at(0)).propertyType == PointPropertyType) {
//            qDebug() << "_________" << this->getObjName() << name << value << "-------------";
            QPointF point;
            //从属性容器中取出点point，并且转换为相对应坐标类型
            if((m_PropertyInfoMap.value(nameList.at(0)).updateType&PointOfRelative)==PointOfRelative)
            {
                if(type == PointDefaultType) {
                    if(m_pItem->parentItem()) {
                        point = m_pItem->mapToParent(m_PropertyInfoMap.value(nameList.at(0)).propertyValue.toPointF());
                    }else {
                        point = m_pItem->mapToScene(m_PropertyInfoMap.value(nameList.at(0)).propertyValue.toPointF());
                    }
                }else if(type == PointParentType) {
                    point = m_pItem->mapToParent(m_PropertyInfoMap.value(nameList.at(0)).propertyValue.toPointF());
                }else if(type == PointSceneType) {
                    point = m_pItem->mapToScene(m_PropertyInfoMap.value(nameList.at(0)).propertyValue.toPointF());
                }
            }else {
                point = m_PropertyInfoMap.value(nameList.at(0)).propertyValue.toPointF();
            }
            //point单个数据赋值
            if(nameList.at(1) == "X") {
                point.setX(value.toReal());
            }else if(nameList.at(1) == "Y") {
                point.setY(value.toReal());
            }
            //赋值后根据坐标类型不同，全部转换为scene坐标
            if((m_PropertyInfoMap.value(nameList.at(0)).updateType&PointOfRelative)==PointOfRelative)
            {
                if(type == PointDefaultType) {
                    if(m_pItem->parentItem()) {
                        tmpValue = m_pItem->mapToScene(m_pItem->mapFromParent(point));
                    }else {
                        tmpValue = point;
                    }
                }else if(type == PointParentType) {
                    tmpValue = m_pItem->mapToScene(m_pItem->mapFromParent(point));
                }else if(type == PointSceneType) {
                    tmpValue = point;
                }
            }else {
                tmpValue = point;
            }

            tmpName = nameList.at(0);
        }
    }
//    qDebug() << this->getGuid() << "object:" << name << value;
    //默认转换
//    GY_Object::UpdatePropertyFun updatePropertyFun = (GY_Object::UpdatePropertyFun)(m_PropertyInfoMap.value(tmpName).updatePropertyFun);
    //GY_PropertyInfo, super_cast强制转换
    GY_Object::UpdatePropertyFun updatePropertyFun = super_cast<GY_Object::UpdatePropertyFun>(m_PropertyInfoMap.value(tmpName).updatePropertyFun);
    if(!m_PropertyInfoMap.contains(tmpName)) {
        return false;
    }
    return (this->*updatePropertyFun)(tmpName,tmpValue);
}

bool GY_Object::getProperty(const QString &name, QVariant &value)
{
    if(!m_PropertyInfoMap.contains(name))
    {
        return false;
    }
    if(m_PropertyInfoMap.value(name).propertyValue.canConvert<QPointF>() &&
            ((m_PropertyInfoMap.value(name).updateType)&PointOfRelative)==PointOfRelative)
    {
        if(m_pItem->parentItem())
        {
            value=m_pItem->mapToParent(m_PropertyInfoMap.value(name).propertyValue.toPointF());
        }
        else
        {
            value=m_pItem->mapToScene(m_PropertyInfoMap.value(name).propertyValue.toPointF());
        }
    }
    else
    {
        value=m_PropertyInfoMap.value(name).propertyValue;
    }

    return true;
}

QVariant GY_Object::submittingPropertyValues(const int &updateType,const QVariant &value,const QGraphicsItem *item)
{
    if((updateType&PointOfRelative)==PointOfRelative)
    {
        if(item->parentItem())
        {
            return item->mapToParent(value.toPointF());
        }
        else
        {
            return item->mapToScene(value.toPointF());
        }
    }
    else if((updateType&AbsolutePoint)==AbsolutePoint)
    {
        return item->mapToScene(value.toPointF());
    }
    return value;
}

QMap<QString, GY_PropertyInfo> GY_Object::getPropertyMap()
{
    return m_PropertyInfoMap;
}

GY_Object *GY_Object::getPurObject(const QString &purposeObjName, GY_Object *obj, QMap<QString, GY_Object *> childrensMap)
{
    QMap<QString,GY_Object*>::Iterator iterName = childrensMap.begin();
    while (iterName != childrensMap.end()) {
        QString objName = iterName.value()->getObjName();
        if(objName == purposeObjName) {
            return iterName.value();
        }
        //如果子类中有容器，再从容器中查找
        if(iterName.value()->getUserData(GY_ENUM::ObjectType) == 1) {
            obj = iterName.value()->getPurObject(purposeObjName, obj, ((GY_ContainerTransform*)iterName.value())->getChildrensMap());
            if(obj != nullptr) {
                return obj;
            }
        }
        ++iterName;
    }
    return obj;
}

bool GY_Object::checkVarName(const QStringList &list, QMap<QString, GY_Object *> childrensMap)
{
    if(list.at(0) == "") {
        return false;
    }
    QMap<QString,GY_Object*>::Iterator iterName = childrensMap.begin();
    while (iterName != childrensMap.end()) {
        QVariant objName;
        objName = iterName.value()->getObjName();
        //查找名称是否存在
        if(objName.toString() == list.at(0)) {
            //查找属性是否存在
            QMap<QString,GY_PropertyInfo> property = iterName.value()->getPropertyMap();
            if(list.size() == 2) {
                if(property.contains(list.at(1))) {
                    return true;
                }
            }
            if(list.size() == 3) {
                if(property.contains(list.at(1)+"."+list.at(2))) {
                    return true;
                }
                if(property.contains(list.at(1))) {
                    if((list.at(2) == "X") || (list.at(2) == "Y")) {
                        return true;
                    }
                }
            }
        }
        //如果子类中有容器，再从容器中查找
        if(iterName.value()->getUserData(GY_ENUM::ObjectType) == 1) {
            bool child = iterName.value()->checkVarName(list, ((GY_ContainerTransform*)iterName.value())->getChildrensMap());
            if(child) {
                return true;
            }
        }
        ++iterName;
    }
    return false;
}

PropertyType GY_Object::getPurposeType(const QStringList &list, QMap<QString, GY_Object *> childrensMap)
{
    QMap<QString,GY_Object*>::Iterator iterType = childrensMap.begin();
    while (iterType != childrensMap.end()) {
        QVariant objName;
        objName = iterType.value()->getObjName();
        //查找名称是否存在
        if(objName.toString() == list.at(0)) {
            //查找属性是否存在
            QMap<QString,GY_PropertyInfo> property = iterType.value()->getPropertyMap();
            if(list.size() == 2) {
                if(property.contains(list.at(1))) {
                    return property[list.at(1)].propertyType;
                }
            }
            if(list.size() == 3) {
                if(property.contains(list.at(1)+"."+list.at(2))) {
                    return property[list.at(1)+"."+list.at(2)].propertyType;
                }
                if(property.contains(list.at(1))) {
                    if((list.at(2) == "X") || (list.at(2) == "Y")) {
                        return property[list.at(1)].propertyType;
                    }
                }
            }
        }
        //如果子类中有容器，再从容器中查找
        if(iterType.value()->getUserData(GY_ENUM::ObjectType) == 1) {
            PropertyType tmp = iterType.value()->getPurposeType(list, ((GY_ContainerTransform*)iterType.value())->getChildrensMap());
            if(tmp != NullPropertyType) {
                return tmp;
            }
        }
        ++iterType;
    }
    return NullPropertyType;
}

void GY_Object::setRepeatNum(const int &num)
{
    m_RepeatNum = num;
}

int GY_Object::getRepeatNum()
{
    return m_RepeatNum;
}

/**
 * @brief initRegisterObject 注册图元类
 */
//void GY_Object::initRegisterObject()
//{

//}

